﻿using Sttplay.Transmission.TCP;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace transmission
{
    public class TCPClientContext : Context
    {
        private TreeViewItem treeItem;
        private StackPanelEx stack;
        public TCPClient client;
        private TCPClient proxy;
        private Image icon = new Image();
        private string ip;
        private int port;
        public SolidColorBrush StateColor { get; private set; }
        public TCPClientContext(TCPReceiver client, string ip = "", int port = 0, bool isProxy = false)
        {
            StateColor = Brushes.Gray;
            this.ip = ip;
            this.port = port;
            if(isProxy)
                proxy = client as TCPClient;
            if (proxy == null)
            {
                this.client = client as TCPClient;
                this.client.onConnectSuccessedEvent += OnConnectedSuccessed;
                this.client.onConnectFailedEvent += OnConnectFailed;
                this.client.onDisconnectEvent += OnDisconnected;
                this.client.onRecvEvent += OnRecv;
            }
            treeItem = new TreeViewItem();
            treeItem.IsExpanded = true;
            stack = new StackPanelEx();
            stack.Orientation = Orientation.Horizontal;
            treeItem.Header = stack;
            
            icon.VerticalAlignment = VerticalAlignment.Center;
            icon.Height = 15;
            icon.Width = 15;
            icon.Margin = new Thickness(0, 0, 4, 0);
            
            stack.Children.Add(icon);
            TextBlock textBlock = new TextBlock();
            textBlock.VerticalAlignment = VerticalAlignment.Center;
            if(proxy != null)
            {
                icon.Source = new BitmapImage(new Uri("pack://application:,,,/res/net_run.png"));
                textBlock.Text = string.Format("{0}", client.Socket.RemoteEndPoint.ToString());
            }
            else
            {
                icon.Source = new BitmapImage(new Uri("pack://application:,,,/res/net_stop.png"));
                textBlock.Text = string.Format("{0}:{1}", ip, port);
            }
            stack.Children.Add(textBlock);
            stack.user = this;
            stack.type = TransmissionType.TcpClient;
            treeItem.IsSelected = true;
        }



        public TreeViewItem GetTreeViewItem()
        {
            return treeItem;
        }

        public TCPClient GetProxy()
        {
            return proxy;
        }

        public override void Tick()
        {
            if (!needUpdateUI) return;
            needUpdateUI = false;
            RecvText = string.Join("\n", recvList.ToArray());
            MainWindow.Instance.UpdateContextText(this);

        }
        public void OnRecv(byte[] buffer)
        {
            string msg = GetRecvBuffer(buffer);
            OnRecvImp(msg, "接收");
        }

        private void OnRecvImp(string msg, string extend)
        {
            recvList.Add(string.Format("[{0} {1}] {2}", DateTime.Now.ToString("HH:mm:ss"), extend, msg));
            while (recvList.Count > MAX_SHOW_LINE)
                recvList.RemoveAt(0);
            needUpdateUI = true;
        }

        public override void Send()
        {
            string str;
            byte[] bs = GetSendBuffer(out str);
            if (bs == null)
                return;
            bool ret = true;
            if (proxy != null)
                ret = proxy.Send(bs, 0, bs.Length);
            else
                ret = client.Send(bs, 0, bs.Length);
            if (ret)
                OnRecvImp(str, "发送");
        }

        public void Connect()
        {
            StateColor = Brushes.Yellow;
            icon.Source = new BitmapImage(new Uri("pack://application:,,,/res/net_connect.png"));
            client.AsyncConnect(IPAddress.Parse(ip), port);
        }


        private void OnConnectFailed(string error)
        {
            StateColor = Brushes.Gray;
            icon.Source = new BitmapImage(new Uri("pack://application:,,,/res/net_stop.png"));
            MainWindow.Instance.OnClientConnectRet(this, false);
        }

        public void OnDisconnected()
        {
            StateColor = Brushes.Gray;
            client.Disconnect();
            OnConnectFailed("");
        }

        private void OnConnectedSuccessed()
        {
            StateColor = new SolidColorBrush(Color.FromRgb(20, 255, 0));
            icon.Source = new BitmapImage(new Uri("pack://application:,,,/res/net_run.png"));
            MainWindow.Instance.OnClientConnectRet(this, true);
        }

        public override void Update()
        {
            base.Update();
            if(client != null)
                client.Update();
        }

        public string GetRemoteIP()
        {
            if(proxy != null)
            {
                return (proxy.Socket.RemoteEndPoint as IPEndPoint).Address.ToString();
            }
            else
            {
                return ip;
            }
        }

        public int GetRemotePort()
        {
            if (proxy != null)
            {
                return (proxy.Socket.RemoteEndPoint as IPEndPoint).Port;
            }
            else
            {
                return port;
            }
        }

        public int GetLocalPort()
        {
            if (proxy != null)
            {
                return (proxy.Socket.LocalEndPoint as IPEndPoint).Port;
            }
            else
            {
                if (client.Socket == null)
                    return -1;
                return (client.Socket.LocalEndPoint as IPEndPoint).Port;
            }
        }
    }
}
